#include <muduo/base/Logging.h>
#include <muduo/base/Thread.h>
#include <muduo/net/TcpClient.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/InetAddress.h>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <stdio.h>

using namespace muduo;
using namespace muduo::net;

class DiscardClient : boost::noncopyable {
public:
	DiscardClient(EventLoop *loop, const InetAddress &listenAddr, int size)
		: loop_(loop),
		  client_(loop, listenAddr, "DiscardClient"),
		  message_(size, 'H') {
		client_.setConnectionCallback(boost::bind(&DiscardClient::OnConnection, this, _1));
		client_.setMessageCallback(boost::bind(&DiscardClient::OnMessage, this, _1, _2, _3));
		client_.setWriteCompleteCallback(boost::bind(&DiscardClient::OnWriteComplete, this, _1));
	}

	void Connect() {
		client_.connect();
	}

private:
	void OnConnection(const TcpConnectionPtr &conn) {
		LOG_INFO << conn->localAddress().toIpPort() << " -> "
		        << conn->peerAddress().toIpPort() << " is "
		        << (conn->connected() ? "UP" : "DOWN"); 
		if (conn->connected()) {
			conn->setTcpNoDelay(true);
			conn->send(message_);
		} else {
			loop_->quit();
		}
	}

	void OnMessage(const TcpConnectionPtr &conn, Buffer *buf, Timestamp time) {
		buf->retrieveAll();
	}

	void OnWriteComplete(const TcpConnectionPtr &conn) {
		LOG_TRACE << "*** write complete" << message_.size();
		conn->send(message_);
	}

	EventLoop *loop_;
	TcpClient client_;
	string message_;
};

int 
main(int argc, char **argv) {
	Logger::setLogLevel(Logger::INFO);
	LOG_INFO << "pid = " << getpid() << ", tid = " << CurrentThread::tid();
	if (argc > 1) {
		EventLoop loop;
		InetAddress serverAddr(argv[1], 2009);

		int size = 256;
		if (argc > 2)
			size = atoi(argv[2]);

		DiscardClient client(&loop, serverAddr, size);
		client.Connect();
		loop.loop();
	} else {
		printf("Usage: %s host_ip [msg_size]\n", argv[0]);
	}
}
